﻿using System;
using System.Collections.Generic;
using NHibernate.Mapping.ByCode;
using Xenta.Enums;

namespace Xenta.Entities
{
    /// <summary>
    /// Represents the rating entity.
    /// </summary>
    /// <remarks><pre>
    /// The entity regarding the disclosure level.
    /// 
    /// + Entire
    ///  + Extended
    ///   + Base
    ///    | - HolderID
    ///    | - Account(of the Keys level)
    ///    | - Comment(of the Base level)
    ///    | - Value
    ///    | - UpdatedOn
    ///    | - CreatedOn
    ///    + Keys
    ///     + Primary
    ///      | - EntityID
    /// 
    /// Note: upper level includes lower level.
    /// </pre></remarks>
    public abstract class RatingEntity : AuditableEntity
    {
        #region Fields

        private AccountEntity _account;
        private CommentEntity _comment;

        #endregion

        #region Ctors

        /// <summary>
        /// Initializes a new class instance.
        /// </summary>
        protected RatingEntity()
        {
            _account = null;
            _comment = null;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the holder identifier.
        /// </summary>
        public virtual int HolderID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the account identifier.
        /// </summary>
        public virtual int AccountID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the account.
        /// </summary>
        public virtual AccountEntity Account
        {
            get
            {
                return AccountID != 0 ? _account : null;
            }
            set
            {
                _account = value;
                AccountID = value != null ? value.EntityID : 0;
            }
        }

        /// <summary>
        /// Gets or sets the comment identifier.
        /// </summary>
        public virtual int CommentID
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the comment.
        /// </summary>
        public virtual CommentEntity Comment
        {
            get
            {
                return CommentID != 0 ? _comment : null;
            }
            set
            {
                _comment = value;
                CommentID = value != null ? value.EntityID : 0;
            }
        }

        /// <summary>
        /// Gets or sets the rating.
        /// </summary>
        public virtual byte Value
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the flags.
        /// </summary>
        public virtual int FlagsValue
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Disclose(IDictionary<String, Object> obj,
            DisclosureLevel level,
            IDictionary<String, String> options)
        {
            base.Disclose(obj, level, options);
            if(level >= DisclosureLevel.Base)
            {
                obj["HolderID"] = HolderID;
                obj["Account"] = Account != null
                    ? Account.Disclose(DisclosureLevel.Keys, options)
                    : null;
                obj["Comment"] = Comment != null
                    ? Comment.Disclose(DisclosureLevel.Base, options)
                    : null;
                obj["Value"] = Value;
            }
        }

        #endregion
    }

    /// <summary>
    /// The entity NHibernate mapping.
    /// </summary>
    public class RatingMapping : EntityMapping<RatingEntity>
    {
        /// <summary>
        /// Initializes a new class instance.
        /// </summary>
        public RatingMapping()
        {
            Table("fwk_Ratings");
            Id(x => x.EntityID, m =>
            {
                m.Column("RatingID");
                m.Generator(Generators.Identity);
            });
            Discriminator(m =>
            {
                m.Column("Discriminator");
                m.Length(10);
                m.Force(true);
                m.NotNullable(true);
            });
            Property(x => x.HolderID, m =>
            {
                m.NotNullable(true);
            });
            Property(x => x.AccountID, m =>
            {
                m.Column("AccountID");
                m.NotNullable(true);
            });
            ManyToOne(x => x.Account, m =>
            {
                m.Column("AccountID");
                m.NotFound(NotFoundMode.Ignore);
                m.Insert(false);
                m.Update(false);
            });
            Property(x => x.CommentID, m =>
            {
                m.Column("CommentID");
                m.NotNullable(true);
            });
            ManyToOne(x => x.Comment, m =>
            {
                m.Column("CommentID");
                m.NotFound(NotFoundMode.Ignore);
                m.Insert(false);
                m.Update(false);
            });
            Property(x => x.Value, m =>
            {
                m.NotNullable(true);
            });
            Property(x => x.FlagsValue, m =>
            {
                m.Column("Flags");
                m.NotNullable(true);
            });
            Property(x => x.CreatedOn, m =>
            {
                m.NotNullable(true);
            });
            Property(x => x.UpdatedOn, m =>
            {
                m.NotNullable(true);
            });
        }
    }
}
